package com.hurst.autotap;

import android.content.Context;
import android.graphics.Point;
import android.net.Uri;
import android.os.Bundle;

import androidx.annotation.Nullable;

import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;

import java.util.HashMap;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_MOVE;
import static android.view.MotionEvent.ACTION_POINTER_DOWN;
import static android.view.MotionEvent.ACTION_POINTER_UP;
import static android.view.MotionEvent.ACTION_UP;


public class FragmentMousePad extends BaseFragment {

    public static final String TAG = "u-FragmentMousePad";
    Button xybutton = null;
    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";
    private String mParam1;
    private String mParam2;

    private OnFragmentInteractionListener mListener;

    public FragmentMousePad() {
    }
    private volatile static FragmentMousePad fragment;
    public static FragmentMousePad getInstance()
    {
        if(fragment == null)
        {
            synchronized (FragmentMousePad.class) {
                if (fragment == null) {
                    fragment = new FragmentMousePad();
                }
            }
        }

        return fragment;
    }
    public static FragmentMousePad newInstance(String param1, String param2) {
        FragmentMousePad fragment = new FragmentMousePad();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_mouse_pad, container, false);
    }

    RelativeLayout padContainer = null;
    EditText editText1 = null;
    EditText editText2 = null;
    LinearLayout pad = null;
    CheckBox checkBox1 = null;
    double screenratio  = 1080d / 1920d;
    int screenWidth = 1080,screenHeight = 1920;
    int padWidth = 0,padHeight = 0;
    double screen2padRatio = 1;
    HashMap<Integer,Integer> PointerId_TouchId = new HashMap<>();
    Queue<Integer> TouchIDPool = new ConcurrentLinkedQueue<>();

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        TouchIDPool.offer(0);
        TouchIDPool.offer(1);
        TouchIDPool.offer(2);
        TouchIDPool.offer(3);
        TouchIDPool.offer(4);
        TouchIDPool.offer(5);
        TouchIDPool.offer(6);
        TouchIDPool.offer(7);

        padContainer = this.getActivity().findViewById(R.id.padContainer);
        editText1 = this.getActivity().findViewById(R.id.editText1);
        editText2 = this.getActivity().findViewById(R.id.editText2);
        pad = this.getActivity().findViewById(R.id.pad);
        checkBox1 = this.getActivity().findViewById(R.id.checkBox1);

        checkBox1.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                String temp = editText1.getText().toString();
                editText1.setText(editText2.getText().toString());
                editText2.setText(temp);
                SetPadsize();
            }
        });

        View.OnClickListener sizeButtonClickListener = new View.OnClickListener(){
            @Override
            public void onClick(View view) {
                Button btn = (Button)view;
                if(btn != null){
                    String st = btn.getText().toString();
                    String[] sts = st.split("\\*");
                    if(sts.length == 2){
                        editText1.setText(sts[0]);
                        editText2.setText(sts[1]);
                        SetPadsize();
                    }
                }
            }
        };

        this.getActivity().findViewById(R.id.button).setOnClickListener(sizeButtonClickListener);
        this.getActivity().findViewById(R.id.button2).setOnClickListener(sizeButtonClickListener);
        this.getActivity().findViewById(R.id.button3).setOnClickListener(sizeButtonClickListener);

        this.getActivity().findViewById(R.id.apply).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                SetPadsize();
            }
        });

        pad.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(final View view, final MotionEvent motionEvent) {
                //region
                switch (motionEvent.getActionMasked()) {
                    case ACTION_DOWN:
                    case ACTION_POINTER_DOWN:
                        int PointerId = motionEvent.getPointerId(motionEvent.getActionIndex());
                        if (TouchIDPool.size() > 0) {
                            if (!PointerId_TouchId.containsKey(PointerId)) {
                                PointerId_TouchId.put(PointerId, TouchIDPool.poll());
                            } else {
                                return false;
                            }
                        } else {
                            return false;
                        }
                        return true;
                    case ACTION_MOVE:
                        for (int i = 0; i < motionEvent.getPointerCount(); i++) {
                            int PointerId1 = motionEvent.getPointerId(i);
                            int TouchID = PointerId_TouchId.get(PointerId1);
                            if (PointerId_TouchId.containsKey(PointerId1) && HidUitls.IsConnected()) {
                                float fx = motionEvent.getX(i);
                                float fy = motionEvent.getY(i);
                                if (fx < padWidth && fy < padHeight && fx >= 0 && fy >= 0) {
                                    Point point = GetPointMap(fx,fy,screen2padRatio);
                                    HidConsts.MTouch_Move_Android(TouchID, point.x, point.y);
                                }
                            }
                        }
                        return true;
                    case ACTION_UP:
                        ReleaseTipSwitch(motionEvent,true);
                        return true;
                    case ACTION_POINTER_UP:
                        ReleaseTipSwitch(motionEvent,false);
                        return true;
                }
                //endregion
                return false;
            }
        });

        UtilCls.DelayTask(new Runnable() {
            @Override
            public void run() {
                getActivity().runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        SetPadsize();
                    }
                });
            }
        },1000,true);


        final EditText editText3 = this.getActivity().findViewById(R.id.editText3);
        final EditText editText4 = this.getActivity().findViewById(R.id.editText4);
        xybutton = getActivity().findViewById(R.id.xybutton);
        xybutton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                int x = Integer.parseInt(editText3.getText().toString());
                int y = Integer.parseInt(editText4.getText().toString());
                Point point = GetPointMap(x,y,1);
                HidConsts.MTouch_Move_Android(1, point.x, point.y);
                HidConsts.MTouch_Reset(1);
            }
        });
    }

    private Point GetPointMap(float x,float y,double screen2padRatio){
        return new Point((int)x,(int)y);
    }

    void ReleaseTipSwitch(MotionEvent motionEvent,boolean resetAll){
        int PointerId3 = motionEvent.getPointerId(motionEvent.getActionIndex());
        int touchid;
        if(TouchIDPool.size() > 0){
            if(PointerId_TouchId.containsKey(PointerId3)){
                touchid = PointerId_TouchId.get(PointerId3);
                PointerId_TouchId.remove(PointerId3);
                TouchIDPool.offer(touchid);
            }else{return;}
        }else{
            return;
        }

        if (HidUitls.IsConnected()) {
            HidConsts.MTouch_Reset(touchid);
        }
    }


    void SetPadsize(){
        final double width = (double)padContainer.getWidth();
        final double height = (double)padContainer.getHeight();
        screenratio  = width / height;
        screenWidth = Integer.parseInt(editText1.getText().toString());
        screenHeight = Integer.parseInt(editText2.getText().toString());
        double mscreenratio  = (double) screenWidth / (double)screenHeight;
        RelativeLayout.LayoutParams linearParams =(RelativeLayout.LayoutParams)pad.getLayoutParams();
        if(screenratio > mscreenratio){
            padWidth = (int) (mscreenratio * height);
            padHeight = (int) height;
        }else if(screenratio < mscreenratio){
            padWidth = (int) width;
            padHeight = (int) (width / mscreenratio);
        }else{
            padWidth = (int) width;
            padHeight = (int) height;
        }
        linearParams.width = padWidth;
        linearParams.height = padHeight;
        pad.setLayoutParams(linearParams);
        screen2padRatio = (double) screenWidth / (double)padWidth;
    }


    void SLog(String log) {
        Log.v("u-mainactivity",log);
    }

    // TODO: Rename method, update argument and hook method into UI event
    public void onButtonPressed(Uri uri) {
        if (mListener != null) {
            mListener.onFragmentInteraction(uri);
        }
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnFragmentInteractionListener) {
            mListener = (OnFragmentInteractionListener) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }
    public interface OnFragmentInteractionListener {
        // TODO: Update argument type and name
        void onFragmentInteraction(Uri uri);
    }
}
